﻿using System.Collections;
using System.Collections.Generic;
using Magiq.Support;
using Magiq.Tests.Support;
using NUnit.Framework;

namespace Magiq.Tests {
    [TestFixture]
    public class ReflectionTests {
        #region Setup/Teardown

        [SetUp]
        public void SetUp() {
            instance = new TestClass
                           {
                               InterfaceProperty = new List<int>(),
                               ValueProperty = 3,
                               NullableProperty = 3,
                               ObjectProperty = "bla",
                               ClassProperty = "bla"
                           };
            nullInstance = new TestClass();
        }

        #endregion

        private TestClass instance;
        private TestClass nullInstance;

        private class TestClass {
            private string classField;
            private IEnumerable interfaceField;
            private int? nullableField;
            private object objectField;

            private int valueField;

            public string ClassProperty {
                get { return classField; }
                set { classField = value; }
            }

            public int ValueProperty {
                get { return valueField; }
                set { valueField = value; }
            }

            public int? NullableProperty {
                get { return nullableField; }
                set { nullableField = value; }
            }

            public object ObjectProperty {
                get { return objectField; }
                set { objectField = value; }
            }

            public IEnumerable InterfaceProperty {
                get { return interfaceField; }
                set { interfaceField = value; }
            }
        }

        [Test]
        public void ShouldGetClassFields() {
            instance.Field("classField").Should(Be.EqualTo(instance.ClassProperty));
        }

        [Test]
        public void ShouldGetClassPropertys() {
            instance.Property("ClassProperty").Should(Be.EqualTo(instance.ClassProperty));
        }

        [Test]
        public void ShouldGetInterfaceFields() {
            instance.Field("interfaceField").Should(Be.EqualTo(instance.InterfaceProperty));
        }

        [Test]
        public void ShouldGetInterfacePropertys() {
            instance.Property("InterfaceProperty").Should(Be.EqualTo(instance.InterfaceProperty));
        }

        [Test]
        public void ShouldGetNullableFields() {
            instance.Field("nullableField").Should(Be.EqualTo(instance.NullableProperty));
        }

        [Test]
        public void ShouldGetNullablePropertys() {
            instance.Property("NullableProperty").Should(Be.EqualTo(instance.NullableProperty));
        }

        [Test]
        public void ShouldGetNullClassFields() {
            nullInstance.Field("classField").Should(Be.EqualTo(nullInstance.ClassProperty));
        }

        [Test]
        public void ShouldGetNullClassPropertys() {
            nullInstance.Property("ClassProperty").Should(Be.EqualTo(nullInstance.ClassProperty));
        }

        [Test]
        public void ShouldGetNullInterfaceFields() {
            nullInstance.Field("interfaceField").Should(Be.EqualTo(nullInstance.InterfaceProperty));
        }

        [Test]
        public void ShouldGetNullInterfacePropertys() {
            nullInstance.Property("InterfaceProperty").Should(Be.EqualTo(nullInstance.InterfaceProperty));
        }

        [Test]
        public void ShouldGetNullNullableFields() {
            nullInstance.Field("nullableField").Should(Be.EqualTo(nullInstance.NullableProperty));
        }

        [Test]
        public void ShouldGetNullNullablePropertys() {
            nullInstance.Property("NullableProperty").Should(Be.EqualTo(nullInstance.NullableProperty));
        }

        [Test]
        public void ShouldGetNullObjectFields() {
            nullInstance.Field("objectField").Should(Be.EqualTo(nullInstance.ObjectProperty));
        }

        [Test]
        public void ShouldGetNullObjectPropertys() {
            nullInstance.Property("ObjectProperty").Should(Be.EqualTo(nullInstance.ObjectProperty));
        }

        [Test]
        public void ShouldGetObjectFields() {
            instance.Field("objectField").Should(Be.EqualTo(instance.ObjectProperty));
        }

        [Test]
        public void ShouldGetObjectPropertys() {
            instance.Property("ObjectProperty").Should(Be.EqualTo(instance.ObjectProperty));
        }

        [Test]
        public void ShouldGetValueFields() {
            instance.Field("valueField").Should(Be.EqualTo(instance.ValueProperty));
        }

        [Test]
        public void ShouldGetValuePropertys() {
            instance.Property("ValueProperty").Should(Be.EqualTo(instance.ValueProperty));
        }

        [Test]
        public void ShouldSetClassProperties() {
            nullInstance.SetProperty("ClassProperty", "lala");
            nullInstance.ClassProperty.Should(Be.EqualTo("lala"));
        }

        [Test]
        public void ShouldSetInterfaceProperties() {
            var value = new List<int>();
            nullInstance.SetProperty("InterfaceProperty", value);
            nullInstance.InterfaceProperty.Should(Be.EqualTo(value));
        }

        [Test]
        public void ShouldSetNullableProperties() {
            nullInstance.SetProperty("NullableProperty", 3);
            nullInstance.NullableProperty.Should(Be.EqualTo(3));
        }

        [Test]
        public void ShouldSetNullClassProperties() {
            nullInstance.SetProperty("ClassProperty", null);
            nullInstance.ClassProperty.Should(Be.Null);
        }

        [Test]
        public void ShouldSetNullInterfaceProperties() {
            nullInstance.SetProperty("InterfaceProperty", null);
            nullInstance.ClassProperty.Should(Be.Null);
        }

        [Test]
        public void ShouldSetNullNullableProperties() {
            nullInstance.SetProperty("NullableProperty", null);
            nullInstance.NullableProperty.Should(Be.Null);
        }

        [Test]
        public void ShouldSetNullObjectProperties() {
            nullInstance.SetProperty("ObjectProperty", null);
            nullInstance.ClassProperty.Should(Be.Null);
        }

        [Test]
        public void ShouldSetObjectProperties() {
            var value = new List<int>();
            nullInstance.SetProperty("ObjectProperty", value);
            nullInstance.ObjectProperty.Should(Be.EqualTo(value));
        }

        [Test]
        public void ShouldSetValueProperties() {
            nullInstance.SetProperty("ValueProperty", 1);
            nullInstance.ValueProperty.Should(Be.EqualTo(1));
        }
    }
}